package services

import (
	"TaskAssignmentSystem/internal/admin/dao"
	"TaskAssignmentSystem/pkg/db/mysql"
	"TaskAssignmentSystem/pkg/oss"
	"errors"
	"fmt"
	"gorm.io/gorm"
	"strings"
)

type DateTimeRange struct {
	StartDateTime string   `json:"start_date_time"`
	EndDateTime   string   `json:"end_date_time"`
	ProjectIds    []string `json:"project_ids"`
}

type DataManageService struct {
	DateTimeRange DateTimeRange
	ProjectIds    []string
}

/*
 * 批量删除选中的项目
 */

func (d *DataManageService) BatchRemoveChangedProjects() error {
	_db := mysql.GetDB()
	return _db.Transaction(func(tx *gorm.DB) error {
		var common CommonService[dao.SystemProject]
		common.Tx = tx
		common.Query = map[string]interface{}{"project_id": d.ProjectIds}
		topicIds := tx.Model(&dao.SystemTopic{}).Where("project_id IN (?)", d.ProjectIds).Select("id")
		//删除题目备注
		if err := tx.Model(&dao.TopicNote{}).Unscoped().Where("system_topic_id IN (?)", topicIds).Delete(&dao.TopicNote{}).Error; err != nil {
			return err
		}
		//删除题目配置
		if err := tx.Model(&dao.TopicConfiguration{}).Unscoped().Where("system_topic_id IN (?)", topicIds).Delete(&dao.TopicConfiguration{}).Error; err != nil {
			return err
		}
		//删除相关项目下的答案
		if err := tx.Model(&dao.TopicAnswer{}).Unscoped().Where("project_id IN (?)", d.ProjectIds).Delete(&dao.TopicAnswer{}).Error; err != nil {
			return err
		}
		//删除项目下的所有答案文件
		for _, projectId := range d.ProjectIds {
			bucketClient := oss.BucketClient{}
			if err := bucketClient.BatchRemoveFiles(fmt.Sprintf("task-assign/%s", projectId)); err != nil {
				return err
			}

		}

		//先删除相关用户记录

		if err := tx.Model(&dao.TopicUserRecord{}).Unscoped().Where("system_topic_id IN (?)", topicIds).Delete(&dao.TopicUserRecord{}).Error; err != nil {
			return err
		}

		//删除相关题目
		if err := tx.Model(&dao.SystemTopic{}).Unscoped().Where("project_id IN (?)", d.ProjectIds).Delete(&dao.SystemTopic{}).Error; err != nil {
			return err
		}
		//删除项目
		if err := common.RemoveUnscoped(); err != nil {
			return err
		}
		return nil
	})

}

/*
 * 批量删除所选时间发放的题目
 */

func (d *DataManageService) RemoveAllTopicForDateTimeRange() error {
	_db := mysql.GetDB()
	return _db.Transaction(func(tx *gorm.DB) error {
		var common CommonService[dao.SystemTopic]
		common.Tx = tx
		common.Query = map[string]interface{}{"project_id": d.ProjectIds}
		if d.DateTimeRange.StartDateTime != "" && d.DateTimeRange.EndDateTime != "" {
			common.WhereStr = append(common.WhereStr, fmt.Sprintf("effective_time BETWEEN '%s' AND '%s'", d.DateTimeRange.StartDateTime, d.DateTimeRange.EndDateTime))
		}
		dtx := tx.Model(&dao.SystemTopic{})
		for _, i := range common.WhereStr {
			dtx.Where(i)
		}
		topicIds := dtx.Where("project_id IN (?)", d.ProjectIds).Select("id")
		//删除题目备注

		if err := tx.Model(&dao.TopicNote{}).Unscoped().Where("system_topic_id IN (?)", topicIds).Delete(&dao.TopicNote{}).Error; err != nil {
			return err
		}
		//删除用户操作题目的记录
		if err := tx.Unscoped().Where("system_topic_id IN (?)", topicIds).Delete(&dao.TopicUserRecord{}).Error; err != nil {
			return err
		}
		//删除题目配置
		if err := tx.Model(&dao.TopicConfiguration{}).Unscoped().Where("system_topic_id IN (?)", topicIds).Delete(&dao.TopicConfiguration{}).Error; err != nil {
			return err
		}
		//删除相关题目的答案
		if err := tx.Model(&dao.TopicAnswer{}).Unscoped().Where("project_id IN (?)", d.ProjectIds).Delete(&dao.TopicAnswer{}).Error; err != nil {
			return err
		}

		res, _ := common.FindNoPreloadAll()
		var projectTopicCount = make(map[string]int, 0)
		//删除题目答案的存储目录
		//bucketClient := oss.BucketClient{}
		for _, topic := range res {
			projectTopicCount[topic.ProjectId] += 1
			//bucketClient.BatchRemoveFiles(fmt.Sprintf("task-assign/%s/%s", topic.ProjectId, topic.TopicId))
		}
		//删除相关题目
		removeRes := dtx.Unscoped().Delete(&dao.SystemTopic{})
		if removeRes.Error != nil || removeRes.RowsAffected == 0 {
			return errors.New("删除题目错误！")
		}

		//更新项目表中题目数
		var projectDao dao.Common[dao.SystemProject]
		for p, v := range projectTopicCount {
			projectDao.Tx = tx
			projectDao.Query = map[string]interface{}{"project_id": p}
			if err := projectDao.Update(map[string]interface{}{"topic_count": gorm.Expr("topic_count - ?", v)}).Error; err != nil {
				return err
			}
		}

		return nil
	})
}

/*
 * 删除题目的答案
 */

func (d *DataManageService) RemoveAllTopicAnswerForDateTimeRange() error {
	_db := mysql.GetDB()
	return _db.Transaction(func(tx *gorm.DB) error {
		var common CommonService[dao.SystemTopic]
		common.Tx = tx
		if d.DateTimeRange.StartDateTime != "" && d.DateTimeRange.EndDateTime != "" {
			common.WhereStr = append(common.WhereStr, fmt.Sprintf("effective_time BETWEEN '%s' AND '%s'", d.DateTimeRange.StartDateTime, d.DateTimeRange.EndDateTime))
		}
		if len(d.ProjectIds) > 0 {
			common.WhereStr = append(common.WhereStr, fmt.Sprintf("project_id IN ('%s')", strings.Join(d.ProjectIds, "','")))
		}
		dtx := tx.Model(&dao.SystemTopic{})
		for _, i := range common.WhereStr {
			dtx.Where(i)
		}
		topicIds := dtx.Model(&dao.SystemTopic{}).Where("project_id IN (?)", d.ProjectIds).Select("id")
		//删除题目答案
		if err := tx.Model(&dao.TopicAnswer{}).Unscoped().Where("system_topic_id IN (?)", topicIds).Delete(&dao.TopicAnswer{}).Error; err != nil {
			return err
		}
		res, _ := common.SelectList()
		//删除题目答案的存储目录
		bucketClient := oss.BucketClient{}
		for _, topic := range res.Data {
			err := bucketClient.BatchRemoveFiles(fmt.Sprintf("task-assign/%s/%s", topic.ProjectId, topic.TopicId))
			if err != nil {
				return err
			}
			fmt.Println("remove oss error is %s", err)
		}

		return nil
	})
}

/*
 * 批量删除所选项目发送的通知
 */

func (d *DataManageService) RemoveChangedProjectMessages() error {
	_db := mysql.GetDB()
	return _db.Transaction(func(tx *gorm.DB) error {
		var common dao.Common[dao.SystemMsg]
		common.Tx = tx
		if err := common.RemoveUnscopedWhere(map[string]interface{}{"permissions": d.ProjectIds}).Error; err != nil {
			return err
		}
		if err := tx.Model(&dao.UserMessage{}).Unscoped().Where("project_id in (?)", d.ProjectIds).Delete(&dao.UserMessage{}).Error; err != nil {
			return err
		}
		return nil
	})
}

type DataListResponse struct {
	Count int64 `json:"count"`
	List  []struct {
		ProjectId   string `json:"project_id"`   //项目自定义Id
		Title       string `json:"title"`        //项目标题
		Cover       string `json:"cover"`        //封面
		TopicCount  int    `json:"topic_count"`  //题目数量
		AnswerSize  int64  `json:"answer_size"`  //答案数据
		AnswerData  string `json:"answer_data"`  //答案数据
		AnswerCount int    `json:"answer_count"` //已回答的题目数
	} `json:"list"`
}

/*
 * 数据管理列表
 */

func (d *DataManageService) DataList(page, pageSize int, timeRange []string) (res DataListResponse, err error) {

	_db := mysql.GetDB()

	subQuery := _db.Model(&dao.SystemProject{})
	err = subQuery.Count(&res.Count).Error
	if err != nil {
		return
	}
	subQuery = subQuery.Select("`tas_system_project`.project_id,ANY_VALUE ( `tas_system_project`.title ) AS title,ANY_VALUE ( cover ) AS cover,`tas_system_topic`.topic_id AS topic_id,SUM( tas_topic_answer.answer_size ) AS answer_size,count( DISTINCT tas_topic_answer.topic_id ) AS answer_count ")

	if len(timeRange) > 0 {
		subQuery = subQuery.Joins(fmt.Sprintf("left join tas_system_topic on `tas_system_project`.project_id = tas_system_topic.project_id AND tas_system_topic.effective_time BETWEEN '%s' AND '%s'", timeRange[0], timeRange[1]))
	} else {
		subQuery = subQuery.Joins(fmt.Sprintf("left join tas_system_topic on `tas_system_project`.project_id = tas_system_topic.project_id"))
	}
	subQuery = subQuery.Joins(fmt.Sprintf("left join tas_topic_answer on `tas_system_topic`.id = tas_topic_answer.system_topic_id"))

	subQuery = subQuery.Group("`tas_system_project`.project_id,`tas_system_topic`.topic_id")
	if err = _db.Table("(?) as u", subQuery).Select("project_id,COUNT( DISTINCT u.topic_id ) AS topic_count,ANY_VALUE ( u.cover ) AS cover,ANY_VALUE ( u.title ) AS title,SUM( u.answer_size ) AS answer_size,SUM( u.answer_count ) AS answer_count ").Group("u.project_id").Offset((page - 1) * pageSize).Limit(pageSize).Find(&res.List).Error; err != nil {
		return
	}
	return
}

func (d *DataManageService) DataList2(page, pageSize int, timeRange []string) (res DataListResponse, err error) {

	_db := mysql.GetDB()

	subQuery := _db.Model(&dao.SystemProject{})
	err = subQuery.Count(&res.Count).Error
	if err != nil {
		return
	}
	subQuery.Select("project_id,title,cover,topic_count,answer_data,answer_count").Where("1=1").Offset((page - 1) * pageSize).Limit(pageSize).Find(&res.List)

	for i, s := range res.List {
		var item_result []struct {
			AnswerSize  int64 `json:"answer_size"`
			AnswerCount int64 `json:"answer_count"`
			Status      int   `json:"status"`
		}
		sql := _db.Model(&dao.SystemTopic{}).Select("SUM( tas_topic_answer.answer_size ) AS answer_size,ANY_VALUE( status ) as status").Where("tas_system_topic.project_id = ?", s.ProjectId)
		if len(timeRange) > 0 {
			sql = sql.Where("tas_system_topic.effective_time BETWEEN ? AND ?", timeRange[0], timeRange[1])
		}
		sql.Joins("left join tas_topic_answer on `tas_system_topic`.id = tas_topic_answer.system_topic_id").Group("`tas_system_topic`.id").Find(&item_result)
		for _, item := range item_result {
			res.List[i].AnswerSize += item.AnswerSize
			if item.Status == 1 {
				res.List[i].AnswerCount += 1
			}

		}
	}
	return
}
